package interceptor

import (
	"Gin-Server-01/com/server/common"
	"Gin-Server-01/com/server/core/tools/jwtTool"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"strings"
	"time"
)

/**
 * @Author XueZhimin
 * @Description
 * @Date 2023/9/5 15:53
 * @Version 1.0
 */

// AllowLoginMiddleware
//
//	@Description:  允许登录中间件
//	@Return: gin.HandlerFunc
func AllowLoginMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		log.Println(fmt.Sprintf("\nXXXXXXXXXXXXXXXXXXXXXXXX【拦截器】XXXXXXXXXXXXXXXXXXXXXXXXX\n"))
		log.Println(fmt.Sprintf("请求方法:%s", c.Request.Method))
		log.Println(fmt.Sprintf("请求地址:%s", c.Request.URL.Path))

		//todo:放行白名单
		var nextFlag bool = false
		//前缀
		if len(common.Configs.WhiteList.SuffixList) > 0 {
			for _, suffix := range common.Configs.WhiteList.SuffixList {
				if strings.HasSuffix(c.Request.URL.Path, suffix) {
					nextFlag = true
				}
			}
		}

		//后缀
		if len(common.Configs.WhiteList.PrefixList) > 0 {
			for _, prefix := range common.Configs.WhiteList.PrefixList {
				if strings.HasPrefix(c.Request.URL.Path, prefix) {
					nextFlag = true
				}
			}
		}
		//等价
		if len(common.Configs.WhiteList.EqualList) > 0 {
			for _, equal := range common.Configs.WhiteList.EqualList {
				if strings.EqualFold(c.Request.URL.Path, equal) {
					nextFlag = true
				}
			}
		}
		if nextFlag {
			c.Next()
		} else {

			//todo:拦截规则:获取header或者cookie的JWT字符串做验证
			//获取header
			token := c.GetHeader(common.TokenKey)
			if len(token) != 0 {
				log.Println(fmt.Sprintf("获取header:%s", token))
			}
			//从cookie获取
			cookieToken, _ := c.Cookie(common.TokenKey)
			if len(cookieToken) != 0 {
				parseToken, err := jwtTool.ParseToken(cookieToken)
				if err != nil {
					//拒绝访问
					c.JSON(http.StatusForbidden, gin.H{
						"title": "非法请求",
						"desc":  "如果想正常访问,请重新登录！",
						"link":  "/login:", //todo:跳转链接
					})
					c.AbortWithStatus(http.StatusForbidden)

					return
				}

				log.Println(fmt.Sprintf("解析的token:↓\n%s", parseToken.JsonString()))

				//获取token的信息
				tokenDatas := jwtTool.TokenDatas{}
				tokenDatas = parseToken.TokenDatas

				//过期时间
				remainingTime := tokenDatas.RemainingTime()
				log.Println(fmt.Sprintf("过期剩余时间:%s", remainingTime))

				//低于20%的时间保活
				keepAlive := tokenDatas.ExpirationTime.Seconds() * 0.2
				log.Println(fmt.Sprintf("触发保活剩余时间线:%s", time.Duration(keepAlive*float64(time.Second))))
				if remainingTime.Seconds() <= keepAlive {
					log.Println(fmt.Sprintf("✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔启动保活机制✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔✔"))

					//类型转化
					tokenMap, ok := parseToken.TokenDatas.TokenData.(map[string]interface{})
					if !ok {
						log.Println("类型不匹配")
						return
					}
					//类型复杂转换
					user := common.LoginUser{
						ClientIp: c.ClientIP(),
						Username: tokenMap["Username"].(string),
						//Auth:     int(tokenMap["Auth"].(float64)),
					}
					log.Println(fmt.Sprintf("%s", user.JsonString()))
					common.RefreshLogin(c, user, remainingTime+common.TokenAlive*time.Duration(2))
				}
			}

			if !tokenIsLegitimate(token) && !tokenIsLegitimate(c.Query(common.TokenKey)) && !tokenIsLegitimate(cookieToken) {

				//拒绝访问
				c.AbortWithStatus(http.StatusForbidden)
			}

		}

		log.Println(fmt.Sprintf("\n========================【拦截器】=========================\n"))

	}
}

// tokenIsLegitimate
//
//	@Description:  判断token合法
//	@Param: token
//	@Return: bool
func tokenIsLegitimate(token string) bool {
	if len(token) == 0 {
		return false
	}
	_, err := jwtTool.ParseToken(token)
	if err != nil {
		log.Println(fmt.Sprintf("解析token错误"))
		return false
	}
	return true
}
